const loadGruntTasks = require('load-grunt-tasks')
const sass = require('sass')
const fs = require('fs-extra')
const browserSync = require('browser-sync').create()
const { program } = require('commander')
const { execSync } = require('child_process')

// 通过commander简化命令行操作
program.option('--port <port>').option('--open').option('--production').option('--prod')
program.parse(process.argv)

let isProd = program.production || program.prod

module.exports = (grunt) => {
  grunt.initConfig({
    // eslint任务
    eslint: {
      target: ['src/assets/scripts/main.js']
    },
    // swig模板编译任务
    swigtemplates: {
      options: {
        defaultContext: {
          date: new Date(),
          pkg: require('./package.json'),
          menus: [
            {
              name: 'Home',
              icon: 'aperture',
              link: 'index.html'
            },
            {
              name: 'Features',
              link: 'features.html'
            },
            {
              name: 'About',
              link: 'about.html'
            },
            {
              name: 'Contact',
              link: '#',
              children: [
                {
                  name: 'Twitter',
                  link: 'https://twitter.com/w_zce'
                },
                {
                  name: 'About',
                  link: 'https://weibo.com/zceme'
                },
                {
                  name: 'divider'
                },
                {
                  name: 'About',
                  link: 'https://github.com/zce'
                }
              ]
            }
          ]
        },
        templatesDir: 'src/'
      },
      production: {
        dest: 'dist/',
        src: ['src/**/*.html']
      },
      staging: {
        dest: 'temp/',
        src: ['src/**/*.html']
      }
    },
    // sass编译任务
    sass: {
      options: {
        implementation: sass
      },
      main: {
        files: {
          'temp/assets/styles/main.css': 'src/assets/styles/main.scss'
        }
      }
    },
    // babel编译任务
    babel: {
      options: {
        presets: ['@babel/preset-env']
      },
      main: {
        files: {
          'temp/assets/scripts/main.js': 'src/assets/scripts/main.js'
        }
      }
    },
    // watch任务，提供browserSync以外的监听
    watch: {
      js: {
        files: ['src/assets/scripts/*.js'],
        tasks: ['babel']
      },
      css: {
        files: ['src/assets/styles/*.scss'],
        tasks: ['sass']
      },
      html: {
        files: ['src/**/*.html'],
        tasks: ['html']
      },
      serve: {
        files: ['src/assets/fonts/**', 'src/assets/images/**', 'public/**'],
        tasks: ['reload']
      }
    },
    // 图片、字体压缩任务
    imagemin: {
      image: {
        files: [{
          expand: true,
          cwd: 'src/assets/images',
          src: ['**/*.{png,jpg,gif,svg,}'],
          dest: 'dist/assets/images'
        }]
      },
      font: {
        files: [{
          expand: true,
          cwd: 'src/assets/fonts',
          src: ['**/*.{eot,svg,ttf,woff}'],
          dest: 'dist/assets/fonts'
        }]
      }
    },
    // 引用文件合并任务，此处使用了自己修改的@minar-kotonoha/grunt-useref
    useref: {
      // specify which files contain the build blocks
      html: 'temp/**/*.html',
      // explicitly specify the temp directory you are working in
      // this is the the base of your links ( "/" )
      temp: 'temp'
    }
  })
  // 加载插件
  loadGruntTasks(grunt)

  // html模板编译完毕后清除目录
  grunt.registerTask('cleanTemplate', () => {
    fs.removeSync('temp/layouts')
    fs.removeSync('temp/partials')
  })

  // 复制静态文件
  grunt.registerTask('extra', () => {
    fs.copySync('public', 'temp')
  })

  // 复制asset
  grunt.registerTask('copyAsset2Dist', () => {
    fs.copySync('src/assets', 'dist/assets')
  })

  // 清除临时目录
  grunt.registerTask('cleanTemp', () => {
    fs.removeSync('temp')
  })

  // 清除目标目录
  grunt.registerTask('cleanDist', () => {
    fs.removeSync('dist')
  })

  // 清除部署目录
  grunt.registerTask('cleanPages', () => {
    fs.removeSync('../../pages')
  })

  // eslint任务别名
  grunt.registerTask('lint', ['eslint'])

  // swigtemplates任务别名
  grunt.registerTask('html', ['swigtemplates:staging'])

  // sass任务别名
  grunt.registerTask('css', ['sass'])

  // babel任务别名
  grunt.registerTask('script', ['babel'])

  // imagemin:image任务别名
  grunt.registerTask('image', ['imagemin:image'])

  // imagemin:font任务别名
  grunt.registerTask('font', ['imagemin:font'])

  // 组合任务：编译html、css、js
  grunt.registerTask('compile', ['clean', 'html', 'cleanTemplate', 'css', 'script'])

  // 组合任务：压缩字体、图片
  grunt.registerTask('asset', ['image', 'font'])

  // 组合任务：清除临时、目标目录
  grunt.registerTask('clean', ['cleanTemp', 'cleanDist'])

  // 组合任务：引用文件、压缩
  grunt.registerTask('userefTask', ['useref', 'concat', 'uglify', 'cssmin'])

  // 启动服务器
  grunt.registerTask('server', function () {
    isProd && this.async()
    const workDir = isProd ? 'dist' : 'temp' // 根据环境确定监听目录
    return browserSync.init({
      notify: !isProd,
      open: program.open,
      port: program.port || 3000,
      files: `${workDir}/**`,
      server: {
        baseDir: [workDir, 'src', 'public'],
        routes: {
          '/node_modules': 'node_modules'
        }
      }
    })
  })

  // 将temp中的内容拷贝到根目录dist文件夹
  grunt.registerTask('copyTemp2Dist', () => {
    fs.copySync('temp', 'dist')
  })

  // 组合任务：开发服务器下build
  grunt.registerTask('buildTemp', ['eslint', 'compile', 'extra'])

  // 组合任务：开发环境下静态build
  grunt.registerTask('buildDev', ['clean', 'buildTemp', 'copyTemp2Dist', 'copyAsset2Dist', 'cleanTemp'])

  // 组合任务：生产环境下静态build
  grunt.registerTask('buildProd', ['eslint', 'compile', 'asset', 'extra', 'userefTask', 'copyTemp2Dist', 'cleanTemp'])

  // 根据环境判断当前build任务
  grunt.registerTask('build', isProd ? ['buildProd'] : ['buildDev'])

  // 组合任务：代码检查、开启服务器、监听
  grunt.registerTask('serve', ['eslint', 'buildTemp', 'server', 'watch'])

  // 将dist中的内容拷贝到根目录pages文件夹
  grunt.registerTask('copy2pages', () => {
    fs.copySync('dist', '../../pages')
  })

  // 提交pages代码到git
  grunt.registerTask('publish2gitee', () => {
    execSync(
      'git add ../../pages && git commit -m "publish pages" && git push origin master'
    )
  })

  // 组合任务：生成静态文件后，清理pages文件夹，复制dist到pages中，最后发布pages
  grunt.registerTask('deploy', ['build', 'cleanPages', 'copy2pages', 'publish2gitee'])

  // 浏览器刷新任务
  grunt.registerTask('reload', browserSync.reload)

  // 设置当前环境为生产
  grunt.registerTask('setProd', () => {
    isProd = true
  })

  // 生产环境下服务器
  grunt.registerTask('start', ['setProd', 'lint', 'buildProd', 'server'])
}
